package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"stick/protocol"
	"stick/utils/common"
	"time"
)

var filePath = flag.String("filePath", "./word.txt", "路径")
var fileType = flag.Int("fileType", 2, "文件类型")

var IdleTime = 60

// ClientConn 连接信息
type ClientConn struct {
	Conn     net.Conn
	Dch      chan struct{}
	FileType byte
	curTime  time.Time
}

func NewClientConn(conn net.Conn, fileType byte) *ClientConn {
	return &ClientConn{
		Dch:      make(chan struct{}),
		Conn:     conn,
		FileType: fileType,
		curTime:  time.Now(),
	}
}

func main() {

	flag.Parse()
	conn, err := net.Dial("tcp", "127.0.0.1:9090")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("连接上 " + conn.RemoteAddr().String() + "....")

	// 3. 处理任务
	clientConn := NewClientConn(conn, byte(*fileType))
	go clientConn.Handler()

	// 4. 发送心跳包
	go clientConn.TimerTask()

	// 5. 检测
	go clientConn.checkHeartbeat()

	<-clientConn.Dch
}

// TimerTask 定时发送心跳包
func (clientConn *ClientConn) TimerTask() {
	timer := time.NewTicker(5 * time.Second)
	for {

		select {
		case <-timer.C:
			fmt.Println("1. 发送心跳包....")
			heartbeatBuf, err := protocol.FileHeaderEncode(
				protocol.Heartbeat,
				protocol.ResponseMessage,
				protocol.FileTypeText,
				protocol.HeartbeatContext)
			if err != nil {
				log.Println("客服端编码失败。。。。", err)
				return
			}

			_, err = clientConn.Conn.Write(heartbeatBuf)
			if err != nil {
				log.Println("服务端已经关闭连接。。。。", err)
				//clientConn.Conn.Close()
				//clientConn.Dch <- true
			}

			fmt.Println("2. 更新本地时间")
			reader := io.Reader(clientConn.Conn)

			data, err := protocol.FileHeaderDecode(reader)
			if data.Heartbeat == protocol.Heartbeat && *data.Content == protocol.HeartbeatContext {
				clientConn.curTime = time.Now()
			}
		}
	}

}

// 超过30秒，关闭连接
func (clientConn *ClientConn) checkHeartbeat() {
	timer := time.NewTicker(5 * time.Second)
	for {
		select {
		case <-timer.C:

			interval := time.Now().Sub(clientConn.curTime) / 1000000000
			fmt.Printf("检测是否超过阈值。。。。。。curTime=%s,interval=%d\n",
				common.ToDetailDate(clientConn.curTime), interval)

			if interval > 30 {
				fmt.Println("超过阈值。。。。")
				clientConn.Conn.Close()
				clientConn.Dch <- struct{}{}
			}
		}
	}
}

// Handler 处理任务
func (clientConn *ClientConn) Handler() {
	fmt.Printf("处理文件类型为：FileType=%d\n", clientConn.FileType)
	switch clientConn.FileType {
	case protocol.FileTypeJson:
		clientConn.JsonWrite()
	case protocol.FileTypeFile:
		clientConn.FileWrite()
	default:

	}
}

func (clientConn *ClientConn) JsonWrite() {
	object := `{"id": "123","comments": "6","name": "sample"}`
	buf, _ := protocol.FileHeaderEncode(
		protocol.NoHeartbeat,
		protocol.NormalMessage,
		protocol.FileTypeJson,
		object)
	clientConn.Conn.Write(buf)
}

// FileWrite 传输文件
func (clientConn *ClientConn) FileWrite() {

	fileInfo, err := os.Stat(*filePath)
	if err != nil {
		fmt.Println("stat  ", err)
		return
	}
	fileName := fileInfo.Name()

	// 1. 输送文件件名称
	buf, _ := protocol.FileHeaderEncode(
		protocol.NoHeartbeat,
		protocol.RequestMessage,
		protocol.FileTypeName,
		fileName)
	clientConn.Conn.Write(buf)

	// 2. 服务端响应的结果
	reader := io.Reader(clientConn.Conn)
	if data, err := protocol.FileHeaderDecode(reader); *data.Content != protocol.AcceptSuccess || err != nil {
		fmt.Println("不能进行文件的写入。。。。。")
		return
	}

	file, err := os.Open(*filePath)
	if err != nil {
		fmt.Println("打开文件失败。。。。。")
		return
	}
	defer file.Close()

	input := bufio.NewScanner(file)
	for input.Scan() {
		buf, err := protocol.FileHeaderEncode(
			protocol.NoHeartbeat,
			protocol.NormalMessage,
			protocol.FileTypeFile,
			input.Text())
		if err != nil {
			fmt.Println("写入失败。。。。 err = ", err)
			return
		}
		clientConn.Conn.Write(buf)
		//time.Sleep(1*time.Second)
	}

	fmt.Println("已经写完。。。。。。")
	finishBuf, err := protocol.FileHeaderEncode(
		protocol.NoHeartbeat,
		protocol.NormalMessage,
		protocol.FileTypeFile,
		protocol.ReadFinish)
	clientConn.Conn.Write(finishBuf)
}
